#if !defined(ANNOTATE_OPTIONS_H)
#define ANNOTATE_OPTIONS_H

#include <string>
#include <map>
#include <iosfwd>

struct COptions
{
	virtual ~COptions(){}
	// enums
	enum JUSTIFY_FLAG		{	JUSTIFY_L, JUSTIFY_C, JUSTIFY_R	};
	enum VALIDRES_FLAG		{	VALID_ALL, VALID_STD, VALID_CUST};
	enum HTMLSTYLES_FLAG	{	S_INLINE, S_CSS					};
	enum COLOURPALETTE_FLAG	{	C_40, C_216						};


	virtual bool set_str(unsigned int /*index*/, const std::string& /*str*/) {return false;}
	virtual bool set_bool(unsigned int /*index*/, const std::string& /*str*/) {return false;}
	virtual bool set_uint(unsigned int /*index*/, const std::string& /*str*/) {return false;}
	virtual bool set_flag(unsigned int /*index*/, const std::string& /*str*/) {return false;}

	// map structures
	enum eOPT_TYPE {eOPT_S, eOPT_B, eOPT_U, eOPT_F};
	struct CLookup_SetOption
	{
		eOPT_TYPE			opt_type;
		unsigned			opt_index;
		COptions&			opt_data;
		CLookup_SetOption(eOPT_TYPE t, unsigned u, COptions& o) : opt_type (t), opt_index(u), opt_data(o){}
	};
	typedef std::map<std::string, CLookup_SetOption> Cmap_options;
	virtual void init_optionsmap(Cmap_options& ) {};
};


struct CHTMLOptions : public COptions
{
	enum	{	eHTMLSampleFont, eHTMLBrowserFontSize, eHTMLWebSafeColours,	// bools
				eHTMLStyleSheets, eColourPalette};							// flags

	CHTMLOptions();
	bool                m_HTMLSampleFont;
	bool                m_HTMLBrowserFontSize;
	bool                m_HTMLWebSafeColours;
	HTMLSTYLES_FLAG     m_HTMLStyleSheets;
	COLOURPALETTE_FLAG  m_ColourPalette;
	
	// persistence
	bool set_bool(unsigned int index, const std::string& str);
    bool set_flag(unsigned int index, const std::string& str);
	void init_optionsmap(Cmap_options& opt);
#ifdef _MFC_VER
	void ToRegistry(CWinApp* app);
	void FromRegistry(CWinApp* app);
#endif
#ifndef NDEBUG
	bool IS_VALID() const;
#endif
};

struct CAnnotateOptions : public COptions
{
	enum	{	eXForUnknown, eIncludeBlanks, eUseElision,					// bools
				eConsensusThreshold, eMinElisionLength, eElisionThreshold}; // flags
	CAnnotateOptions();
	bool                m_XForUnknown;
	bool                m_IncludeBlanks;
	bool                m_UseElision;
	unsigned                m_ConsensusThreshold;
	unsigned                m_MinElisionLength;
	unsigned                m_ElisionThreshold;
	
	// persistence
	bool				set_bool(unsigned int index, const std::string& str);
    bool				set_uint(unsigned int index, const std::string& str);
	void				init_optionsmap(Cmap_options& opt);
#ifdef _MFC_VER
	void ToRegistry(CWinApp* app);
	void FromRegistry(CWinApp* app);
#endif
#ifndef NDEBUG
	bool IS_VALID() const;
#endif
};

struct CParseOptions : public COptions
{
	CParseOptions();
	bool                m_ConfirmDataFormats;
	bool                m_MergePHDPredictions;
	bool                m_IgnoreConfidences;
	bool                m_Ignore_COIL;
	bool                m_AllowLowerCase;
	bool                m_AllowStrangeLinkers;
	VALIDRES_FLAG       m_OnlyValidAAs;
	std::string         m_InvalidResidueLetters;
	// persistence
	enum {	eMergePHDPredictions, eIgnoreConfidences, eIgnore_COIL,         // bools
			eAllowLowerCase, eAllowStrangeLinkers,							// bools
			eOnlyValidAAs,													// flags
			eInvalidResidueLetters	};										// str / char
	bool				set_bool(unsigned int index, const std::string& str);
	bool				set_str(unsigned int index, const std::string& str);
	bool				set_flag(unsigned int index, const std::string& str);
	void				init_optionsmap(Cmap_options& opt);
#ifdef _MFC_VER
	void ToRegistry(CWinApp* app);
	void FromRegistry(CWinApp* app);
#endif
#ifndef NDEBUG
	bool IS_VALID() const;
#endif
};

struct COutputOptions : public COptions
{
	COutputOptions();
	unsigned                m_ColumnWidth;				
	unsigned                m_WrapOutputLen;
	std::string         m_SubstitutedLinkers;
	bool                m_WrapOutput;
	bool                m_OutputConsensusThreshold;
	bool                m_ForceToUpper;
	bool                m_SubstituteLinker;
	bool                m_ColumnSpaces;
	bool                m_SetDuplicates;
	bool                m_MultipleSets;
	char                m_SubstitutingLinker;
	JUSTIFY_FLAG        m_JustifyName;
	// persistence
	enum {	eColumnWidth, 													// uint
			eSubstitutedLinkers, 											// str
			eWrapOutputLen, 												// bools
			eWrapOutput, eOutputConsensusThreshold, eForceToUpper, 			// bools
			eSubstituteLinker, eColumnSpaces, eSetDuplicates, eMultipleSets,// bools
			eSubstitutingLinker, 											// str / char
			eJustifyName};													// flags
	bool				set_bool(unsigned int index, const std::string& str);
    bool				set_uint(unsigned int index, const std::string& str);
	bool				set_str(unsigned int index, const std::string& str);
	bool				set_flag(unsigned int index, const std::string& str);
	void				init_optionsmap(Cmap_options& opt);
#ifdef _MFC_VER
	void ToRegistry(CWinApp* app);
	void FromRegistry(CWinApp* app);
#endif
#ifndef NDEBUG
	bool IS_VALID() const;
#endif
};

struct CGeneralOptions : public COptions
{
	CGeneralOptions();
	unsigned                m_MRUCount;
	unsigned                m_MRUConfigCount;
	bool                m_ToolbarLarge;
	bool                m_Verbose;
#ifdef _MFC_VER
	void ToRegistry(CWinApp* app);
	void FromRegistry(CWinApp* app);
#endif
#ifndef NDEBUG
	bool IS_VALID() const;
#endif
};


template<class _Elem, class _Traits>
std::basic_ostream<_Elem, _Traits>& operator<<(	std::basic_ostream<_Elem, _Traits>& ostrm,
										  const CHTMLOptions& opt)
{
	ostrm << "Use \"SAMPLE\" font="				<< opt.m_HTMLSampleFont << std::endl;
	ostrm << "Use Browser Font Size Settings="	<< opt.m_HTMLBrowserFontSize << std::endl;
	ostrm << "Check for web-safe colours="		<< opt.m_HTMLWebSafeColours << std::endl;
	ostrm << "Use style Sheets="					<< opt.m_HTMLStyleSheets << std::endl;
	ostrm << "Colour Palette="					<< opt.m_ColourPalette << std::endl;
	return ostrm;
}

template<class _Elem, class _Traits>
std::basic_ostream<_Elem, _Traits>& operator<<(	std::basic_ostream<_Elem, _Traits>& ostrm,
										  const CAnnotateOptions& opt)
{
	ostrm << "X is for Unknown=" 			<< opt.m_XForUnknown << std::endl;
	ostrm << "Consensus Threshold="			<< opt.m_ConsensusThreshold << std::endl;
	ostrm << "Include Blanks=" 				<< opt.m_IncludeBlanks << std::endl;
	ostrm << "Use Elision=" 				<< opt.m_UseElision << std::endl;
	ostrm << "Minimum Elision Length=" 		<< opt.m_MinElisionLength << std::endl;
	ostrm << "Elision Threshold=" 			<< opt.m_ElisionThreshold << std::endl;
	return ostrm;
}
template<class _Elem, class _Traits>
std::basic_ostream<_Elem, _Traits>& operator<<(	std::basic_ostream<_Elem, _Traits>& ostrm,
										  const CParseOptions& opt)
{
	ostrm << "DSC Ignore Coil=" 				<< opt.m_Ignore_COIL << std::endl;
	ostrm << "Merge PHD predictions=" 			<< opt.m_MergePHDPredictions << std::endl;
	ostrm << "Restrict to Valid AAs=" 			<< opt.m_OnlyValidAAs << std::endl;
	ostrm << "Invalid Residues=" 				<< opt.m_InvalidResidueLetters << std::endl;
	ostrm << "Confirm Data Formats=" 			<< opt.m_ConfirmDataFormats << std::endl;
	ostrm << "Allow lower case=" 				<< opt.m_AllowLowerCase << std::endl;
	ostrm << "Allow strange linkers=" 			<< opt.m_AllowStrangeLinkers << std::endl;
	ostrm << "Ignore 2ndary struct confidences=" << opt.m_IgnoreConfidences << std::endl;
	return ostrm;
}


template<class _Elem, class _Traits>
std::basic_ostream<_Elem, _Traits>& operator<<(	std::basic_ostream<_Elem, _Traits>& ostrm,
										  const COutputOptions& opt)
{
	ostrm << "Column width=" 					<< opt.m_ColumnWidth << std::endl;
	ostrm << "Wrap Output Length=" 				<< opt.m_WrapOutputLen << std::endl;
	ostrm << "Substituted Linkers=" 			<< opt.m_SubstitutedLinkers << std::endl;
	ostrm << "Wrap Output="			 			<< opt.m_WrapOutput << std::endl;
	ostrm << "Output Consensus Threshold=" 		<< opt.m_OutputConsensusThreshold << std::endl;
	ostrm << "Enforce Upper=" 					<< opt.m_ForceToUpper << std::endl;
	ostrm << "Enforce Linker Character=" 		<< opt.m_SubstituteLinker << std::endl;
	ostrm << "Separate columns with spaces="	<< opt.m_ColumnSpaces << std::endl;
	ostrm << "Duplicate sequences in sets=" 	<< opt.m_SetDuplicates << std::endl;
	ostrm << "Multiple alignment sets=" 		<< opt.m_MultipleSets << std::endl;
	ostrm << "Substituting Linker Character="	<< opt.m_SubstitutingLinker << std::endl;
	ostrm << "Name Justification="	 			<< opt.m_JustifyName << std::endl;
	return ostrm;
}

#endif // !defined(ANNOTATE_OPTIONS_H)


